module vga_top_apb(
  input         clock,
  input         reset,
  input  [31:0] in_paddr,
  input         in_psel,
  input         in_penable,
  input  [2:0]  in_pprot,
  input         in_pwrite,
  input  [31:0] in_pwdata,
  input  [3:0]  in_pstrb,
  output        in_pready,
  output [31:0] in_prdata,
  output        in_pslverr,

  output [7:0]  vga_r,
  output [7:0]  vga_g,
  output [7:0]  vga_b,
  output        vga_hsync,
  output        vga_vsync,
  output        vga_valid
);

  // address space: 0x2100_0000~0x211f_ffff

  wire in_valid;
  wire [31:0] vga_addr;
  wire [31:0] size;

  reg pready;
  reg [31:0] vga_ram[307199:0];

  reg [31:0] count0;
  reg [31:0] count1;
  reg [31:0] prdata;

  assign in_valid = in_psel && in_penable;
  assign vga_addr = (in_paddr - 32'h2100_0008) / 4;
  assign size = (in_pstrb == 4'b0001 || in_pstrb == 4'b0010 || in_pstrb == 4'b0100 || in_pstrb == 4'b1000) ? 1 :
                (in_pstrb == 4'b0011 || in_pstrb == 4'b1100) ? 2 :
                (in_pstrb == 4'b1111) ? 4 : 0;

  assign in_prdata  = 0;
  assign in_pslverr = 0;
  assign in_pready  = pready;
  assign in_prdata  = prdata;

  // write
  always @(posedge clock) begin
    if (in_valid && in_pwrite) vga_ram[vga_addr] <= in_pwdata;
  end
  always @(posedge clock or posedge reset) begin
    if (reset) pready <= 1'b0;
    else if (pready) pready <= 1'b0;
    else if (in_valid && !pready) pready <= 1'b1;
  end

  // read
  always @(posedge clock or posedge reset) begin
    if (reset) begin
      count0 <= 0;
      count1 <= 0;
    end
    else if (count0 == 32'hffffffff) begin
      count0 <= 0;
      count1 <= count1 + 1;
    end
    else begin
      count0 <= count0 + 1;
      count1 <= count1;
    end
  end
  always @(posedge clock or posedge reset) begin
    if (reset) prdata <= 32'd0;
    else if (in_valid && ~in_pwrite)
      prdata <= in_paddr == 32'h2100_0000 ? count0 : in_paddr == 32'h2100_0004 ? count1 : 32'd0;
  end

  // output vga signals
  parameter h_frontporch = 96;
  parameter h_active = 144;
  parameter h_backporch = 784;
  parameter h_total = 800;

  parameter v_frontporch = 2;
  parameter v_active = 35;
  parameter v_backporch = 515;
  parameter v_total = 525;

  reg [31:0] vga_data;
  reg [9:0]  x_cnt;
  reg [9:0]  y_cnt;
  wire       h_valid;
  wire       v_valid;
  wire [9:0] h_addr;
  wire [9:0] v_addr;

  always @(posedge clock) begin
    if(reset == 1'b1) begin
      x_cnt <= 1;
      y_cnt <= 1;
    end
    else begin
      if(x_cnt == h_total)begin
        x_cnt <= 1;
        if(y_cnt == v_total) y_cnt <= 1;
        else y_cnt <= y_cnt + 1;
      end
      else x_cnt <= x_cnt + 1;
    end
  end

  //生成同步信号
  assign vga_hsync = (x_cnt > h_frontporch);
  assign vga_vsync = (y_cnt > v_frontporch);
  //生成消隐信号
  assign h_valid   = (x_cnt > h_active) & (x_cnt <= h_backporch);
  assign v_valid   = (y_cnt > v_active) & (y_cnt <= v_backporch);
  assign vga_valid = h_valid & v_valid;
  //计算当前有效像素坐标
  assign h_addr = h_valid ? (x_cnt - 10'd145) : 10'd0;
  assign v_addr = v_valid ? (y_cnt - 10'd36) : 10'd0;
  //设置输出的颜色值
  assign vga_data = vga_ram[v_addr * 640 + h_addr];
  assign {vga_r, vga_g, vga_b} = vga_valid ? vga_data[23:0] : 24'd0;

endmodule
